using System;
using AndyPike.Commons.Web.MonoRail.Binders;
using AndyPike.Commons.Web.MonoRail.Helpers;
using AndyPike.Snowflake.Core.Exceptions;
using AndyPike.Snowflake.Core.Messages;
using AndyPike.Snowflake.Core.Services;
using AndyPike.Snowflake.Web.Controllers.Base;
using AndyPike.Snowflake.Web.Enums;
using Castle.MonoRail.Framework;

namespace AndyPike.Snowflake.Web.Controllers
{
    [Helper(typeof(CaptchaHelper), "captcha")]
    public class AccountController : PublicController
    {
        private readonly IAccountService accountService;

        public AccountController(IAccountService accountService)
        {
            this.accountService = accountService;
        }

        [DefaultAction]
        public void New()
        {
            RenderView("New");
        }

        [AccessibleThrough(Verb.Post)]
        public void Create([DataBind("registration")]RegistrationMessage registration, [CaptchaBind]bool isHuman)
        {
            if (!isHuman)
            {
                HandleRegistrationError(registration, Error.FailedCaptcha);
                return;
            }

            try
            {
                Guid authenticationToken = accountService.RegisterAccount(registration);
                Response.CreateCookie("authenticationToken", authenticationToken.ToString(), DateTime.Now.AddYears(1));
                Redirect("My", "Dashboard");
            }
            catch (DuplicateUserNameException)
            {
                HandleRegistrationError(registration, Error.DuplicateUserName);
            }
            catch (InvalidUserNameException)
            {
                HandleRegistrationError(registration, Error.InvalidUserName);
            }
            catch (InvalidPasswordException)
            {
                HandleRegistrationError(registration, Error.InvalidPassword);
            }
            catch (InvalidEmailException)
            {
                HandleRegistrationError(registration, Error.InvalidEmail);
            }
        }

        private void HandleRegistrationError(RegistrationMessage registration, Error error)
        {
            registration.Password = string.Empty;

            Flash["error"] = error;
            Flash["registration"] = registration;
            RedirectToAction("New");
        }

        public void Logout()
        {
            Response.RemoveCookie("authenticationToken");
            RedirectToAction("LoggedOut");
        }
        
        public void LoggedOut()
        {
            RenderView("LoggedOut");
        }

        public void Login()
        {
            RenderView("Login");
        }

        [AccessibleThrough(Verb.Post)]
        public void Authenticate([DataBind("credentials")]CredentialsMessage credentials)
        {
            try
            {
                Guid authenticationToken = accountService.AuthenticateCredentials(credentials);
                Response.CreateCookie("authenticationToken", authenticationToken.ToString(), DateTime.Now.AddYears(1));
                Redirect("My", "Dashboard");
            }
            catch (AuthenticationFailedException)
            {
                Flash["error"] = Error.AuthenticationFailed;
                RedirectToAction("Login");
            }
        }
    }
}